/**
 * Copyright (C) 2017 - 2020 https://github.com/joewee
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.bifrost.task;

import com.alibaba.fastjson.JSON;
import com.bifrost.constant.OrderType;
import com.bifrost.entity.Order;
import com.bifrost.entity.OrderTransaction;
import com.bifrost.event.OrderPaidEvent;
import com.bifrost.exception.CancelOrderException;
import com.bifrost.repository.OrderTransactionRepository;
import com.bifrost.service.OrderService;
import com.bifrost.service.OrderStatusHistoryService;
import com.bifrost.service.PayService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.handler.IJobHandler;
import com.xxl.job.core.handler.annotation.JobHandler;
import com.xxl.job.core.log.XxlJobLogger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.math.BigInteger;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;

/**
 * 取消超时未支付订单
 *
 * @author joewee
 * @version 1.0.0
 * @Date 2017/12/3 17:57
 */
@Component
@JobHandler("cancelOrderTask")

public class CancelOrderTask extends IJobHandler{
    private Logger logger = LoggerFactory.getLogger(CancelOrderTask.class);
    @Autowired
    OrderService orderService;
    @Autowired
    PayService payService;
    @Autowired
    OrderStatusHistoryService statusHistoryService;
    @Autowired
    OrderTransactionRepository orderTransactionRepository;
    @Autowired
    ApplicationContext context;
    @Value("${wechat.order.expire:#{30}}")
    private long expire;

    public void execute() {}

    @Override
    public ReturnT<String> execute(String s) throws Exception {

        Queue<Order> queue = new LinkedList<>();
        XxlJobLogger.log("执行取消超时未支付订单任务开始");
        logger.info("开始执行取消超时未支付订单任务...");
        List<Order> unpaidOrders = orderService.findAllUnpaidOrders();
        if (unpaidOrders != null && !unpaidOrders.isEmpty()) {
            unpaidOrders.forEach(order -> {
                queue.offer(order);
            });
            Order order = queue.peek();
            while (order != null) {
                try {
                    logger.info(String.format("当前订单：%d", order.getOrderId()));
                    Date purchasedTime = order.getDatePurchased();
                    if (purchasedTime.getTime()+expire*60*1000 <= System.currentTimeMillis()) {
                        logger.info(String.format("开始取消订单：%d", order.getOrderId()));
                        //调用付款查询接口查询是否付款
                        Map<String,String> result = payService.query(order.getOutTradeNo(),null);
                        if("0".equals(result.get("status"))&&"0".equals(result.get("result_code"))){
                            String trade_state= result.get("trade_state");
                            /**
                             * SUCCESS—支付成功
                             * REFUND—转入退款
                             * NOTPAY—未支付
                             * CLOSED—已关闭
                             * REVERSE—已冲正
                             * REVOK—已撤销
                             * */
                            if(!"SUCCESS".equals(trade_state)){
                                if(OrderType.CASH_BY_COUPON.equalsIgnoreCase(order.getOrderType())){
                                    orderService.cancelUnpaidCouponOrder(order.getCustomer(),order.getOrderId(),String.format("超过30分钟未付款，系统将自动取消"));
                                }else {
                                    orderService.cancelUnpaidOrder(order.getCustomer(), order.getOrderId(), String.format("超过30分钟未付款，系统将自动取消"));
                                }
                                // 弹出队列
                                logger.info(String.format("取消订单：%d成功", order.getOrderId()));
                            }else{
                                //TODO 未接收到通知的订单通过查询确认付款后的处理
                                //记录交易日志
                                String totalFee = result.get("total_fee");
                                OrderTransaction transaction = new OrderTransaction();
                                transaction.setOrder(order);
                                transaction.setPaymentType(order.getPayment().getDescription());
                                transaction.setTransactionAmount(totalFee);
                                transaction.setTransactionDate(new Date());
                                transaction.setTransactionType("unified.trade.query");
                                transaction.setBusinessId(result.get("transaction_id"));
                                transaction.setUpdatedTimestamp(new Date());
                                transaction.setTransactionDetails(String.format("交易成功：%s", JSON.toJSONString(result)));
                                orderTransactionRepository.save(transaction);
                                OrderPaidEvent orderPaidEvent = new OrderPaidEvent(order.getOutTradeNo(), new BigInteger(totalFee));
                                context.publishEvent(orderPaidEvent);
                            }
                        }else{
                            if(OrderType.CASH_BY_COUPON.equalsIgnoreCase(order.getOrderType())){
                                orderService.cancelUnpaidCouponOrder(order.getCustomer(),order.getOrderId(),String.format("超过30分钟未付款，系统将自动取消"));
                            }else {
                                orderService.cancelUnpaidOrder(order.getCustomer(), order.getOrderId(), String.format("超过30分钟未付款，系统将自动取消"));
                            }
                            // 弹出队列
                            logger.info(String.format("取消订单：%d成功", order.getOrderId()));
                        }
                    } else {
                        try {
                            Thread.sleep((purchasedTime.getTime()+expire*60*1000)-System.currentTimeMillis());
                        } catch (InterruptedException e) {
                            logger.error(e.getMessage(), e);
                        }
                    }
                }catch (CancelOrderException ex){
                    logger.error(String.format("订单：%d取消失败",order.getOrderId()),ex);
                }catch (IllegalArgumentException ex){
                    logger.error(String.format("取消订单：%s失败", ex.getMessage()));
                }
                catch (Exception ex) {
                    logger.error(String.format("取消订单：%s失败", ex.getMessage()), ex);
                }finally {
                    //防止死循环
                    queue.poll();
                    // 取下一个元素
                    order = queue.peek();
                }
            }
        }
        XxlJobLogger.log("执行取消超时未支付订单任务完成");
        return ReturnT.SUCCESS;
    }
}
